
// 去除参数中为空的时候不显示
export const getParamsRequiredKeys = (allPrams = {}, specialKeys = []) => {
  // 过滤特殊键的空值
  const filteredSpecialParams = Object.fromEntries(
    Object.entries(allPrams).filter(
      ([key, value]) => !specialKeys.includes(key) || (value !== null && value !== undefined && value !== "")
    )
  )
  return {
    ...filteredSpecialParams,
    // 过滤掉其他空值
    ...Object.fromEntries(
      Object.entries(allPrams).filter(
        ([key, value]) => !specialKeys.includes(key) && value !== null && value !== undefined && value !== ""
      )
    )
  }
}
/**
 * 获取对象的嵌套属性值
 * @param {Object} obj - 要操作的对象
 * @param {string|Array} path - 属性路径，可以是点分隔的字符串（如'a.b.c'）或数组（如['a','b','c']）
 * @param {*} defaultValue - 如果路径不存在，返回的默认值
 * @returns {*} 找到的属性值或默认值
 */
export const getNestedValue = (obj, path, defaultValue = undefined) => {
  if (!obj || typeof obj !== 'object') return defaultValue;

  // 如果path是字符串，按照点号分割
  const keys = typeof path === 'string' ? path.split('.') : Array.isArray(path) ? path : [path];

  let result = obj;
  for (const key of keys) {
    if (result === undefined || result === null) return defaultValue;
    result = result[key];
  }

  return result !== undefined ? result : defaultValue;
}

/**
 * 设置对象的嵌套属性值
 * @param {Object} obj - 要操作的对象
 * @param {string|Array} path - 属性路径，可以是点分隔的字符串（如'a.b.c'）或数组（如['a','b','c']）
 * @param {*} value - 要设置的值
 * @returns {Object} 修改后的对象
 */
export const setNestedValue = (obj, path, value) => {
  if (!obj || typeof obj !== 'object') return obj;

  // 如果path是字符串，按照点号分割
  const keys = typeof path === 'string' ? path.split('.') : Array.isArray(path) ? path : [path];

  if (keys.length === 0) return obj;

  let current = obj;
  const lastKey = keys.pop();

  for (const key of keys) {
    if (current[key] === undefined || current[key] === null || typeof current[key] !== 'object') {
      // 如果下一级是数字索引，则创建数组，否则创建对象
      const nextKey = keys[keys.indexOf(key) + 1];
      current[key] = !isNaN(parseInt(nextKey)) ? [] : {};
    }
    current = current[key];
  }

  current[lastKey] = value;
  return obj;
}

/**
 * 切换对象中嵌套的布尔值属性
 * @param {Object} obj - 要操作的对象
 * @param {string|Array} path - 属性路径，指向一个布尔值
 * @returns {Object} 修改后的对象
 */
export const toggleNestedBoolean = (obj, path) => {
  if (!obj || typeof obj !== 'object') return obj;

  const currentValue = getNestedValue(obj, path, false);
  if (typeof currentValue !== 'boolean') {
    console.warn(`路径 ${path} 的值不是布尔类型`);
    return obj;
  }

  setNestedValue(obj, path, !currentValue);
  return obj;
}

/**
 * 向对象的嵌套数组属性添加元素
 * @param {Object} obj - 要操作的对象
 * @param {string|Array} path - 属性路径，指向一个数组
 * @param {*} item - 要添加的元素
 * @param {boolean} unique - 是否确保元素唯一性，为true时如果元素已存在则不添加
 * @returns {Object} 修改后的对象
 */
export const addToNestedArray = (obj, path, item, unique = false) => {
  if (!obj || typeof obj !== 'object') return obj;

  const arr = getNestedValue(obj, path, []);
  if (!Array.isArray(arr)) {
    console.warn(`路径 ${path} 的值不是数组类型`);
    return obj;
  }

  // 如果需要唯一性检查且元素已存在，则不添加
  if (unique && arr.includes(item)) {
    return obj;
  }

  const newArr = [...arr, item];
  setNestedValue(obj, path, newArr);
  return obj;
}
/**
 * 向对象的嵌套数组属性添加对象元素
 * @param {Object} obj - 要操作的对象
 * @param {string|Array} path - 属性路径，指向一个数组
 * @param {Object} itemObj - 要添加的对象
 * @param {boolean} unique - 是否确保元素唯一性，为true时如果元素已存在则不添加
 * @returns {Object} 修改后的对象
 */
export const addObjectToNestedArray = (obj, path, itemObj, unique = false) => {
  if (!obj || typeof obj !== 'object') return obj;
  if (!itemObj || typeof itemObj !== 'object') {
    console.warn('添加的元素不是对象类型');
    return obj;
  }

  const arr = getNestedValue(obj, path, []);
  if (!Array.isArray(arr)) {
    console.warn(`路径 ${path} 的值不是数组类型`);
    return obj;
  }

  // 如果需要唯一性检查且对象已存在，则不添加
  if (unique) {
    const exists = arr.some(item =>
      item && typeof item === 'object' && JSON.stringify(item) === JSON.stringify(itemObj)
    );
    if (exists) return obj;
  }

  const newArr = [...arr, itemObj];
  setNestedValue(obj, path, newArr);
  return obj;
}

/**
 * 从对象的嵌套数组属性中移除元素
 * @param {Object} obj - 要操作的对象
 * @param {string|Array} path - 属性路径，指向一个数组
 * @param {*} item - 要移除的元素
 * @returns {Object} 修改后的对象
 */
export const removeFromNestedArray = (obj, path, item) => {
  if (!obj || typeof obj !== 'object') return obj;

  const arr = getNestedValue(obj, path, []);
  if (!Array.isArray(arr)) {
    console.warn(`路径 ${path} 的值不是数组类型`);
    return obj;
  }

  const newArr = arr.filter(element => element !== item);
  setNestedValue(obj, path, newArr);
  return obj;
}

/**
 * 更新对象嵌套数组中特定索引的元素
 * @param {Object} obj - 要操作的对象
 * @param {string|Array} path - 属性路径，指向一个数组
 * @param {number} index - 要更新的元素索引
 * @param {*} newValue - 新的元素值
 * @returns {Object} 修改后的对象
 */
export const updateNestedArrayItem = (obj, path, index, newValue) => {
  if (!obj || typeof obj !== 'object') return obj;

  const arr = getNestedValue(obj, path, []);
  if (!Array.isArray(arr)) {
    console.warn(`路径 ${path} 的值不是数组类型`);
    return obj;
  }

  if (index < 0 || index >= arr.length) {
    console.warn(`索引 ${index} 超出数组范围`);
    return obj;
  }

  const newArr = [...arr];
  newArr[index] = newValue;
  setNestedValue(obj, path, newArr);
  return obj;
}

/**
 * 判断数组是否为空
 * @param {Array} arr - 要检查的数组
 * @returns {boolean} 如果数组为空或不是数组则返回true，否则返回false
 */
export const isArrayEmpty = (arr) => {
  return !Array.isArray(arr) || arr.length === 0;
}
/**
 * 合并数组到对象的嵌套数组属性
 * @param {Object} obj - 要操作的对象
 * @param {string|Array} path - 属性路径，指向一个数组
 * @param {Array} newArray - 要合并的新数组
 * @param {boolean} unique - 是否确保元素唯一性，为true时会去除重复元素
 * @returns {Object} 修改后的对象
 */
export const mergeNestedArray = (obj, path, newArray, unique = false) => {
  if (!obj || typeof obj !== 'object') return obj;
  if (!Array.isArray(newArray)) {
    console.warn('合并的元素不是数组类型');
    return obj;
  }

  const arr = getNestedValue(obj, path, []);
  if (!Array.isArray(arr)) {
    console.warn(`路径 ${path} 的值不是数组类型`);
    return obj;
  }

  let mergedArray;
  if (unique) {
    // 使用Set去重
    mergedArray = [...new Set([...arr, ...newArray])];
  } else {
    mergedArray = [...arr, ...newArray];
  }

  setNestedValue(obj, path, mergedArray);
  return obj;
}

/**
 * 重置对象的嵌套数组属性
 * @param {Object} obj - 要操作的对象
 * @param {string|Array} path - 属性路径，指向一个数组
 * @param {Array} newArray - 新的数组值，默认为空数组
 * @returns {Object} 修改后的对象
 */
export const resetNestedArray = (obj, path, newArray = []) => {
  if (!obj || typeof obj !== 'object') return obj;
  if (newArray !== undefined && !Array.isArray(newArray)) {
    console.warn('提供的新值不是数组类型');
    return obj;
  }

  setNestedValue(obj, path, newArray);
  return obj;
}

/**
 * 重置对象的嵌套对象属性
 * @param {Object} obj - 要操作的对象
 * @param {string|Array} path - 属性路径，指向一个对象
 * @param {Object} newObj - 新的对象值，默认为空对象
 * @returns {Object} 修改后的对象
 */
export const resetNestedObject = (obj, path, newObj = {}) => {
  if (!obj || typeof obj !== 'object') return obj;
  if (newObj !== undefined && (typeof newObj !== 'object' || newObj === null || Array.isArray(newObj))) {
    console.warn('提供的新值不是对象类型');
    return obj;
  }

  setNestedValue(obj, path, newObj);
  return obj;
}

/**
 * 创建通用的Vuex/Pinia store getters
 * 提供获取各种类型嵌套属性值的便捷方法
 */
export const createCommonGetters = {
  getValue: (state) => (path, defaultValue) => {
    if (!state) {
      console.error('state 对象不存在');
      return defaultValue;
    }
    return getNestedValue(state, path, defaultValue);
  },

  getBoolean: (state) => (path, defaultValue = false) => {
    if (!state) {
      console.error('state 对象不存在');
      return defaultValue;
    }
    const value = getNestedValue(state, path, defaultValue);
    return typeof value === 'boolean' ? value : defaultValue;
  },

  getArray: (state) => (path, defaultValue = []) => {
    if (!state) {
      console.error('state 对象不存在');
      return defaultValue;
    }
    const value = getNestedValue(state, path, defaultValue);
    return Array.isArray(value) ? value : defaultValue;
  },

  /**
   * 判断指定路径的数组是否为空
   * @param {string|Array} path - 属性路径，指向一个数组
   * @returns {boolean} 如果数组为空或不存在则返回true，否则返回false
   */
  isArrayEmpty: (state) => (path) => {
    if (!state) {
      console.error('state 对象不存在');
      return true;
    }
    const arr = getNestedValue(state, path, []);
    return isArrayEmpty(arr);
  },

  getObject: (state) => (path, defaultValue = {}) => {
    if (!state) {
      console.error('state 对象不存在');
      return defaultValue;
    }
    const value = getNestedValue(state, path, defaultValue);
    return typeof value === 'object' && value !== null && !Array.isArray(value) ? value : defaultValue;
  },
}

/**
 * 创建通用的Vuex/Pinia store actions
 * 提供修改各种类型嵌套属性值的便捷方法
 * @param {Object} store - store实例，如果不提供则使用this
 * @returns {Object} 包含各种操作方法的actions对象
 */
export const createCommonActions = (store = null) => {
  return {
    /**
     * 设置任意嵌套属性值
     * @param {string|Array} path - 属性路径
     * @param {*} value - 要设置的值
     */
    setValue(path, value) {
      const target = store || this;
      if (!target) {
        console.error('store 对象不存在');
        return;
      }
      setNestedValue(target, path, value);
    },

    /**
     * 切换布尔值
     * @param {string|Array} path - 指向布尔值的属性路径
     */
    toggleBoolean(path) {
      const target = store || this;
      if (!target) {
        console.error('store 对象不存在');
        return;
      }
      toggleNestedBoolean(target, path);
    },

    /**
     * 向数组添加元素
     * @param {string|Array} path - 指向数组的属性路径
     * @param {*} item - 要添加的元素
     * @param {boolean} unique - 是否确保元素唯一性
     */
    addToArray(path, item, unique = false) {
      const target = store || this;
      if (!target) {
        console.error('store 对象不存在');
        return;
      }
      addToNestedArray(target, path, item, unique);
    },

    /**
     * 从数组移除元素
     * @param {string|Array} path - 指向数组的属性路径
     * @param {*} item - 要移除的元素
     */
    removeFromArray(path, item) {
      const target = store || this;
      if (!target) {
        console.error('store 对象不存在');
        return;
      }
      removeFromNestedArray(target, path, item);
    },

    /**
     * 更新数组中特定索引的元素
     * @param {string|Array} path - 指向数组的属性路径
     * @param {number} index - 要更新的元素索引
     * @param {*} newValue - 新的元素值
     */
    updateArrayItem(path, index, newValue) {
      const target = store || this;
      if (!target) {
        console.error('store 对象不存在');
        return;
      }
      updateNestedArrayItem(target, path, index, newValue);
    },

    /**
     * 向数组添加对象元素
     * @param {string|Array} path - 指向数组的属性路径
     * @param {Object} itemObj - 要添加的对象
     * @param {boolean} unique - 是否确保元素唯一性
     */
    addObjectToArray(path, itemObj, unique = false) {
      const target = store || this;
      if (!target) {
        console.error('store 对象不存在');
        return;
      }
      addObjectToNestedArray(target, path, itemObj, unique);
    },
    
    /**
     * 合并数组
     * @param {string|Array} path - 指向数组的属性路径
     * @param {Array} newArray - 要合并的新数组
     * @param {boolean} unique - 是否确保元素唯一性
     */
    mergeArray(path, newArray, unique = false) {
      const target = store || this;
      if (!target) {
        console.error('store 对象不存在');
        return;
      }
      mergeNestedArray(target, path, newArray, unique);
    },

    /**
     * 重置数组
     * @param {string|Array} path - 指向数组的属性路径
     * @param {Array} newArray - 新的数组值，默认为空数组
     */
    resetArray(path, newArray = []) {
      const target = store || this;
      if (!target) {
        console.error('store 对象不存在');
        return;
      }
      resetNestedArray(target, path, newArray);
    },
    
    /**
     * 重置对象
     * @param {string|Array} path - 指向对象的属性路径
     * @param {Object} newObj - 新的对象值，默认为空对象
     */
    resetObject(path, newObj = {}) {
      const target = store || this;
      if (!target) {
        console.error('store 对象不存在');
        return;
      }
      resetNestedObject(target, path, newObj);
    },

    /**
     * 合并对象
     * @param {string|Array} path - 指向对象的属性路径
     * @param {Object} newObj - 要合并的新对象
     */
    mergeObject(path, newObj) {
      const target = store || this;
      if (!target) {
        console.error('store 对象不存在');
        return;
      }
      const currentObj = getNestedValue(target, path, {});
      if (typeof currentObj !== 'object' || currentObj === null || Array.isArray(currentObj)) {
        console.warn(`路径 ${path} 的值不是对象类型`);
        return;
      }
      setNestedValue(target, path, { ...currentObj, ...newObj });
    },
  }
}
